class Order < ApplicationRecord
  STATES = %w(new paying processing succeeded failed canceled)

  belongs_to :payer
  belongs_to :payment_request
  belongs_to :charge
  has_one :plan, through: :payment_request

  validates :payment_request_id, uniqueness: { message: '该学生订单已生成' }
  validates :state, inclusion: {in: STATES}
  validates :credit_card_num, length: {
      maximum: 50,
      message: '银行卡号长度应不超过50个字符'
  }
  validates :credit_card_holder, length: {
      maximum: 50,
      minimum: 2,
      message: '持卡人姓名长度应在2至50个字符之间'
  }
  validates :bank, length: {
      maximum: 50,
      message: '开户银行长度应不超过50个字符'
  }
  validates :parent_name, length: {
      maximum: 50,
      minimum: 2,
      message: '家长姓名长度应在2至50个字符之内'
  }
  validates :parent_mobile, format: {
      with: /\A1\d{10}\z/,
      message: '家长手机号格式错误'
  }

  # after_update :increment_plan_paid_count

  before_create :generate_order_num

  after_save :create_or_update_history

  def confirm(transaction_code, payment_username)
    transaction do
      update(transaction_code: transaction_code, payment_username: payment_username, state: 'succeeded', completed_at: Time.now)
      plan.increment!(:paid_count)
      # OrderHistory.find(id).payment_notifications.create(payment_method: payment_method)
    end
  end

  def reject(state = 'failed')
    transaction do
      history = OrderHistory.find(id)
      history.assign_attributes(attributes.merge('state' => state, 'completed_at' => Time.now).reject{|k, _| k.in? %w(id lock_version)}.to_h)
      history.save
      destroy
      history
    end
  end

  STATES.each do |state|
    define_method :"#{state}?" do
      self.state == state
    end
  end
  alias paid succeeded?
  alias paid? succeeded?

  def completed?
    self.state.in? %w(succeeded failed canceled)
  end

  def generate_order_num
    self.order_num = (created_at.to_i * 10_000_000 + payment_request_id % 10_000_000)
                         .to_s(33)
                         .upcase
                         .tr('I', 'X')
                         .tr('O', 'Y')
  end

  private

  def create_or_update_history
    history = OrderHistory.find_or_initialize_by(id: id).tap{|h| h.id = id}
    history.assign_attributes(attributes.reject{|k, _| k.in? %w(id lock_version)}.to_h)
    history.save
  end

end
